Шаг 3. Совмещаем merge, rebase и cherry-pick

Мы создали точную копию коммита, находящегося в ветке main. Теперь нужно сделать перебазирование коммита из этой же ветки. Если этого не сделать и сразу влить ветку 04-demo-cherry-pick в main, то слияние пройдёт с использованием режима no-fast-forward. Будет создан коммит слияния, а ещё у нас будет два коммита с одинаковым текстом.

Сделаем небольшое отступление и разберём ещё две дополнительные опции для команды git rebase.

Если мы сейчас пропишем команду git rebase, то скопированный коммит будет сначала прочитан, затем удалён, и только после этого будет добавлен перебазированный коммит. По умолчанию для этого используется опция --no-reapply-cherry-picks (её необязательно прописывать). Но она не очень выгодна: так как коммиты проходят сначала этап прочтения, и при большом количестве коммитов производительность может упасть.

Можно использовать другую опцию — --reapply-cherry-picks. Она позволяет повторно применить скопированные коммиты и заменить старые хэши на новые. То есть те, которые находятся в целевой ветке, и которые нам нужны. Старые хэши также будут удалены после этого.

При использовании и первой, и второй опции итог один — вопрос только в производительности. Кроме того, разработчики Git рекомендуют использовать опцию --reapply-cherry-picks. Дополнительно отметим: если вы будете использовать опцию --no-reapply-cherry-picks или команду git rebase без опций после создания точной копии коммита, то получите в выводе от Git рекомендацию перейти на опцию --reapply-cherry-picks.

Переходим к практике.

Пропишем команду — git rebase main --reapply-cherry-picks.

Введена команда git rebase main --reapply-cherry-picks
Введена команда git rebase main --reapply-cherry-picks

Мы снова столкнулись с конфликтом. Быстро решим его вручную.

Сначала приведём код к тому же состоянию, что и было до этого.

Код после внесённых изменений
Код после внесённых изменений

После этого перейдём в Git Bash и добавим наши изменения в индекс — git add --all.

Введена команда git add --all
Введена команда git add --all

Затем продолжим перебазирование. Для этого пропишем команду git rebase --continue.

Введена команда git rebase --continue
Введена команда git rebase --continue

Снова открылся файл COMMIT_EDITMSG. Так как текст коммита редактировать не нужно, просто сохраним файл с помощью сочетания клавиш Ctrl + S, а затем закроем — нажмём на крестик.

Снова вернёмся в Git Bash и увидим конечный вывод команды git rebase.

Вывод Git после использования команды git rebase
Вывод Git после использования команды git rebase

Там написано, что мы сейчас находимся в состоянии detached HEAD и у нас ещё есть возможность откатить текущее перебазирование. Отмены операций мы тоже будем разбирать, но в другом разделе. Также в этом выводе написано, что удалён старый хэш, который был присвоен коммиту после использования команды git cherry-pick. Давайте проверим, какой сейчас хэш у коммита. Для этого воспользуемся командой git log --oneline -2.

Введена команда git log --oneline -2
Введена команда git log --oneline -2

Хэш первого коммита изменился, а второго, который прибыл с ветки main, остался прежним — это нам и нужно.

Теперь переключимся на ветку main, чтобы выполнить слияние. Для этого воспользуемся командой git switch main.

Введена команда git switch main
Введена команда git switch main

Затем вольём ветку 04-demo-cherry-pick в ветку main. Для этого пропишем команду git merge 04-demo-cherry-pick.

Введена команда git merge 04-demo-cherry-pick
Введена команда git merge 04-demo-cherry-pick

Всё отлично, слияние произошло с использованием режима fast-forward. Конфликтов нет, потому что мы их решили на временной ветке.

Удалим временную ветку — она выполнила свою задачу и больше не нужна нам. Используем команду git branch --delete 04-demo-cherry-pick.

Введена команда git branch --delete 04-demo-cherry-pick
Введена команда git branch --delete 04-demo-cherry-pick

Почти готово — осталось только отправить изменения в удалённый репозиторий. Вводим команду git push.

Введена команда git push
Введена команда git push

Изменения отправлены в удалённый репозиторий.